#ifndef __EPOLL_SERVER_HPP__
#define __EPOLL_SERVER_HPP__

#include <iostream>
#include <string>
#include <cassert>
#include <functional>
#include "Sock.hpp"
#include "Epoll.hpp"

namespace ns_epoll
{
    const static int default_port = 8080;
    const static int max_fds = 64;

    class EpollServer
    {
        using func_t = std::function<void(std::string)>;
    public:
        EpollServer(func_t _HandlerRequest, const int& port = default_port)
        : _port(port), _evs_count(max_fds), _HandlerRequest(_HandlerRequest)
        {
            // 申请空间
            _evs_array = new struct epoll_event[_evs_count];
            // 创建监听套接字
            _listensock = Sock::Socket();
            Sock::Bind(_listensock, _port);
            Sock::Listen(_listensock);
            // 创建epoll 模型
            _epfd = Epoll::EpollCreate();
            logMessage(NORMAL, "init server success, listensock: %d, epfd: %d", _listensock, _epfd);
            // 将监听套接字加入到epoll
            if(!Epoll::EpollCtl(_epfd, EPOLL_CTL_ADD, _listensock, EPOLLIN))
                exit(6);
            logMessage(NORMAL, "add listen sock to epoll success");
        }

        ~EpollServer()
        {
            if(_evs_array) delete[] _evs_array;
            if(_listensock >= 0)  close(_listensock);
            if(_epfd >= 0) close(_epfd);
        }

        void Start()
        {
            int timeout = -1;
            while(true)
            {
                // 事件循环 持续运行
                LoopOnce(timeout);
            }
        }

        void LoopOnce(int timeout)
        {
            // 等待事件就绪
            int n = Epoll::EpollWait(_epfd, _evs_array, _evs_count, timeout);
            switch(n)
            {
            case 0: // 超时
                logMessage(DEBUG, "EpollWait time out.");
                break;
            case -1: // 错误
                logMessage(WARNING, "epoll wait error | %d : %s", errno, strerror(errno));
                break;
            default: // 成功
                logMessage(DEBUG, "EpollWait success, get a event.");
                HandlerEvents(n);
                break;
            }
        }

        void HandlerEvents(int n)
        {

            assert(n > 0);
            for(int i = 0; i < n; ++i)
            {
                uint32_t revents = _evs_array[i].events;
                int sock = _evs_array[i].data.fd;
                // 读事件就绪
                if(revents & EPOLLIN){
                    if(sock == _listensock) Accepter(_listensock); // 建立连接
                    else Recver(sock); // 接收事件
                }

                if(revents & EPOLLOUT){
                    // 待完善
                }
            }
        }

        void Accepter(const int _listensock)
        {
            std::string clientIp; // ip
            uint16_t clientPort; // 端口
            int sock = Sock::Accept(_listensock, &clientIp, &clientPort); // 建立连接
            if(sock < 0) { // 连接失败
                logMessage(WARNING, "accept error | %d : %s", errno, strerror(errno));
                return;
            }

            if(!Epoll::EpollCtl(_epfd, EPOLL_CTL_ADD, sock, EPOLLIN)) return; // 如果为0，证明sock无法添加到epoll，失败了
            logMessage(NORMAL, "add new client sock to epoll success, sock: %d", sock);
        }

        void Recver(const int sock)
        {
            char buffer[1024];
            ssize_t n = recv(sock, buffer, sizeof(buffer)-1, 0); // 接收数据
            if(n > 0){
                buffer[n] = '\0';
                _HandlerRequest(buffer); // 处理数据
            } else if(n == 0) { // 对端退出
                // 先在epoll取消对sock的关注
                bool ret = Epoll::EpollCtl(_epfd, EPOLL_CTL_DEL, sock, 0);
                assert(ret);
                (void) ret;
                // 关闭sock
                close(sock);
                logMessage(DEBUG, "client[%d] sock quit, me too.", sock);
            } else { // 读取失败
                bool ret = Epoll::EpollCtl(_epfd, EPOLL_CTL_DEL, sock, 0);
                assert(ret); (void)ret;
                // 关闭sock
                close(sock);
                logMessage(WARNING, "recv error | %d : %s", errno, strerror(errno));
            }
        }

    private:
        uint16_t _port; // 端口
        int _listensock; // 监听套接字
        int _epfd; // epoll 文件描述符
        int _evs_count;
        struct epoll_event* _evs_array;
        func_t _HandlerRequest; // 处理请求的函数
    };
}

#endif